/*******************************************************************************
 * ATE, Automation Test Engine
 *
 * Copyright 2015, Montreal PROT, or individual contributors as
 * indicated by the @author tags or express copyright attribution
 * statements applied by the authors.  All third-party contributions are
 * distributed under license by Montreal PROT.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *******************************************************************************/
package utils;

//import com.opera.core.systems.OperaDriver;

import common_types.BrowserType;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
//import org.openqa.selenium.phantomjs.PhantomJSDriver;
//import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.safari.SafariDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeSuite;

import java.util.*;

import static common_types.BrowserType.FIREFOX;

/**
 * The Class BrowserUtil.
 */
public class BrowserUtil {//NOPMD

	/** The _prop. */
	private static ResourceBundle _prop = ResourceBundle.getBundle("dev");// NOPMD
	
	/** The browser type. */
	private static BrowserType browserType;
	
	/** The web drivers. */
	private static List<WebDriver> webDrivers = Collections
			.synchronizedList(new ArrayList<WebDriver>());
	
	/** The driver for thread. */
	private static ThreadLocal<WebDriver> driverForThread = new ThreadLocal<WebDriver>() {

		/**
		 * {@inheritDoc}
		 */
		@Override
		protected WebDriver initialValue() {
			WebDriver driver = loadWebDriver();
			webDrivers.add(driver);
			return driver;
		}
	};

	/**
	 * Sets the up test.
	 */
	@BeforeSuite
	public static void setUpTest() {// NOPMD
		for (BrowserType browser : BrowserType.values()) {
			if (browser.toString().toLowerCase() // NOPMD
					.equals(_prop.getString("browser").toLowerCase())) {
				browserType = browser;
			}
		}
		if (browserType == null) {// NOPMD
			System.err // NOPMD
					.println("Unknown browser specified, defaulting to 'Firefox'...");
			browserType = FIREFOX;
		}
	}

	/**
	 * Tear down.
	 */
	@AfterSuite
	public static void tearDown() { //NOPMD
		for (WebDriver driver : webDrivers) {
			driver.quit();
		}
	}

	/**
	 * Clear cookies.
	 */
	@AfterMethod
	public static void clearCookies() {
		getDriver().manage().deleteAllCookies();
	}

	/**
	 * Gets the driver.
	 *
	 * @return the driver
	 */
	protected static WebDriver getDriver() {
		return driverForThread.get();
	}

	private static DesiredCapabilities generateDesiredCapabilities(
			final BrowserType capabilityType) {
		DesiredCapabilities capabilities;

		switch (capabilityType) {// NOPMD
		case IE:
			capabilities = DesiredCapabilities.internetExplorer();
			capabilities.setCapability(
					CapabilityType.ForSeleniumServer.ENSURING_CLEAN_SESSION,
					true);
			capabilities.setCapability(
					InternetExplorerDriver.ENABLE_PERSISTENT_HOVERING, true);
			capabilities.setCapability("requireWindowFocus", true);
			break;
		case SAFARI:
			capabilities = DesiredCapabilities.safari();
			capabilities.setCapability("safari.cleanSession", true);
			break;
//		case OPERA:
//			capabilities = DesiredCapabilities.opera();
//			capabilities.setCapability("opera.arguments", "-nowin -nomail");
//			break;
		// case GHOSTDRIVER:
		// capabilities = DesiredCapabilities.phantomjs();
		// capabilities.setCapability("takesScreenshot", true);
		// if
		// (System.getProperties().getProperty("os.arch").toLowerCase().equals("x86_64")
		// ||
		// System.getProperties().getProperty("os.arch").toLowerCase().equals("amd64"))
		// {
		// if
		// (System.getProperties().getProperty("os.name").toLowerCase().contains("windows"))
		// {
		// capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
		// _prop.getString("binaryRootFolder") +
		// "/windows/phantomjs/64bit/1.9.7/phantomjs.exe");
		// } else if
		// (System.getProperties().getProperty("os.name").toLowerCase().contains("mac"))
		// {
		// capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
		// _prop.getString("binaryRootFolder") +
		// "/osx/phantomjs/64bit/1.9.7/phantomjs");
		// } else if
		// (System.getProperties().getProperty("os.name").toLowerCase().contains("linux"))
		// {
		// capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
		// _prop.getString("binaryRootFolder") +
		// "/linux/phantomjs/64bit/1.9.7/phantomjs");
		// }
		// } else {
		// if
		// (System.getProperties().getProperty("os.name").toLowerCase().contains("windows"))
		// {
		// capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
		// _prop.getString("binaryRootFolder") +
		// "/windows/phantomjs/32bit/1.9.7/phantomjs.exe");
		// } else if
		// (System.getProperties().getProperty("os.name").toLowerCase().contains("mac"))
		// {
		// capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
		// _prop.getString("binaryRootFolder") +
		// "/osx/phantomjs/32bit/1.9.7/phantomjs");
		// } else if
		// (System.getProperties().getProperty("os.name").toLowerCase().contains("linux"))
		// {
		// capabilities.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY,
		// _prop.getString("binaryRootFolder") +
		// "/linux/phantomjs/32bit/1.9.7/phantomjs");
		// }
		// }
		// break;
		case CHROME:
			capabilities = DesiredCapabilities.chrome();
			capabilities.setCapability("chrome.switches",
					Arrays.asList("--no-default-browser-check"));
			HashMap<String, String> chromePreferences = new HashMap<String, String>();
			chromePreferences.put("profile.password_manager_enabled", "false");
			capabilities.setCapability("chrome.prefs", chromePreferences);
			break;
		case FIREFOX:
			capabilities = DesiredCapabilities.firefox();
			break;
		case HTMLUNIT:
		default:
			capabilities = DesiredCapabilities.htmlUnit();
			capabilities.setCapability("javascriptEnabled", "true");
		}

		return capabilities;
	}

	/**
	 * Load web driver.
	 *
	 * @return the web driver
	 */
	private static WebDriver loadWebDriver() {// NOPMD
		System.out.println("Current Operating System: "// NOPMD
				+ System.getProperties().getProperty("os.name"));// NOPMD
		System.out.println("Current Architecture: "// NOPMD
				+ System.getProperties().getProperty("os.arch"));// NOPMD
		System.out.println("Current Browser Selection: " + browserType);// NOPMD

		// Load standalone executable if required
		switch (browserType) {//NOPMD
		case CHROME:
			if (System.getProperties().getProperty("os.arch").toLowerCase()// NOPMD
					.equals("x86_64")
					|| System.getProperties().getProperty("os.arch")// NOPMD
							.toLowerCase().equals("amd64")) {
				if (System.getProperties().getProperty("os.name").toLowerCase()
						.contains("windows")) {
					System.setProperty(
							"webdriver.chrome.driver",// NOPMD
							_prop.getString("binaryRootFolder")// NOPMD
									+ "/windows/googlechrome/64bit/2.9/chromedriver.exe");
				} else if (System.getProperties().getProperty("os.name")
						.toLowerCase().contains("mac")) {
					System.setProperty(
							"webdriver.chrome.driver",
							_prop.getString("binaryRootFolder")
									+ "/osx/googlechrome/64bit/2.9/chromedriver");
				} else if (System.getProperties().getProperty("os.name")
						.toLowerCase().contains("linux")) {
					System.setProperty(
							"webdriver.chrome.driver",
							_prop.getString("binaryRootFolder")
									+ "/linux/googlechrome/64bit/2.9/chromedriver");
				}
			} else {
				if (System.getProperties().getProperty("os.name").toLowerCase()
						.contains("windows")) {
					System.setProperty(
							"webdriver.chrome.driver",
							_prop.getString("binaryRootFolder")
									+ "/windows/googlechrome/32bit/2.9/chromedriver.exe");
				} else if (System.getProperties().getProperty("os.name")
						.toLowerCase().contains("mac")) {
					System.setProperty(
							"webdriver.chrome.driver",
							_prop.getString("binaryRootFolder")
									+ "/osx/googlechrome/32bit/2.9/chromedriver");
				} else if (System.getProperties().getProperty("os.name")
						.toLowerCase().contains("linux")) {
					System.setProperty(
							"webdriver.chrome.driver",
							_prop.getString("binaryRootFolder")
									+ "/linux/googlechrome/32bit/2.9/chromedriver");
				}
			}
			break;
		case IE:
			if (System.getProperties().getProperty("os.arch").toLowerCase()// NOPMD
					.equals("x86_64")
					|| System.getProperties().getProperty("os.arch")// NOPMD
							.toLowerCase().equals("amd64")) {// NOPMD
				System.setProperty(
						"webdriver.ie.driver",
						_prop.getString("binaryRootFolder")
								+ "/windows/internetexplorer/64bit/2.41.0/IEDriverServer.exe");
			} else {
				System.setProperty(
						"webdriver.ie.driver",
						_prop.getString("binaryRootFolder")
								+ "/windows/internetexplorer/32bit/2.41.0/IEDriverServer.exe");
			}
			break;
		}

		// Instantiate driver object
		switch (browserType) {
		case FIREFOX:
			return new FirefoxDriver(generateDesiredCapabilities(browserType)); // NOPMD
		case CHROME:
			return new ChromeDriver(generateDesiredCapabilities(browserType));// NOPMD
		case IE:
			return new InternetExplorerDriver(// NOPMD
					generateDesiredCapabilities(browserType));// NOPMD
		case SAFARI:
			return new SafariDriver(generateDesiredCapabilities(browserType));// NOPMD
			// case OPERA:
			// return new OperaDriver(generateDesiredCapabilities(browserType));
			// case GHOSTDRIVER:
			// return new
			// PhantomJSDriver(generateDesiredCapabilities(browserType));
		default:
			return new HtmlUnitDriver(generateDesiredCapabilities(browserType));// NOPMD
		}
	}
}
